package rubik;

import java.util.Random;

import rubik.crossover.ICrossOverFunc;
import rubik.fitness.IFitnessFunc;
import rubik.mutators.ICubeSolutionMutator;
import rubik.seqs.ISequenceGenerator;

import evo.IInstance;
import evo.IInstanceBuilder;

public class CubeBuilder implements IInstanceBuilder {

	private static final int RAND_MOVES = 100;
	
	private static Random r = new Random();
	
	private Cube _cube;

	private ICubeSolutionMutator _mutator;

	private ISequenceGenerator _seqgen;
	
	private IFitnessFunc _fitnessFunc;
	
	private ICrossOverFunc _crossOverFunc;

	public CubeBuilder (ICubeSolutionMutator mutator, ISequenceGenerator seqgen, IFitnessFunc fitnessFunc, ICrossOverFunc croosOverFunc)
	{
		this._seqgen = seqgen;
		this._mutator = mutator;
		this._fitnessFunc = fitnessFunc;
		this._crossOverFunc = croosOverFunc;
		this._cube = new Cube();
		
		EMove[] moves = EMove.values();
		for (int i = 0; i < RAND_MOVES; i++) {
			EMove move = moves[r.nextInt(moves.length)];
			this._cube.turn(move.getFace(), move.isCCW());
			//System.out.println();
			//System.out.println(this._cube);
		}
		this._cube.save();
		//System.out.println(this._cube);
	}
	
	public CubeBuilder (Cube cube, ICubeSolutionMutator mutator, ISequenceGenerator seqgen, IFitnessFunc fitnessFunc, ICrossOverFunc croosOverFunc)
	{
		this._seqgen = seqgen;
		this._mutator = mutator;
		this._fitnessFunc = fitnessFunc;
		this._crossOverFunc = croosOverFunc;
		this._cube = cube;
		this._cube.save();
		//System.out.println(this._cube);
	}
	
	@Override
	public IInstance createRandom() {
		CubeSolution sol = new CubeSolution(this._cube,this._seqgen,this._mutator,this._fitnessFunc, this._crossOverFunc);
		sol.randomize();
		sol.calculateFitness();
		return sol;
	}

	@Override
	public IInstance[] createRandom(int n) {
		IInstance[] res = new IInstance[n];
		for (int i = 0; i < res.length; i++) {
			res[i] = this.createRandom();
		}
		return res;
	}
	
	public Cube getCube()
	{
		return this._cube;
	}

}
